package tjs.study.notes.dotest.proxy.javassist.agent.other;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import tjs.study.notes.dotest.TjsStudyNotesApplication;

import java.lang.reflect.Field;

/**
 * Created by Nicky.Tang on 2021/10/12 10:31 上午
 *
 * @since 02.12.10
 */
public class 熟悉api {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.makeClass("tjs.study.notes.dotest.jvm.class_6_1_类文件结构.TestOutOfMemory");
        int maxSize = 99999;
        for (int i = 128; i <= maxSize; i++) {
            //String field = "public static Integer a" + i + " = "+i+";";//这样无效，agent不会自动拆箱装箱
            String field = "public static Integer a" + i + " = new Integer("+i+");";
            ctClass.addField(CtField.make(field, ctClass));

//            CtField ctField = new CtField(pool.get(Integer.class.getName()), "a"+i, ctClass);
//            ctField.setModifiers(Modifier.PUBLIC + Modifier.STATIC + Modifier.FINAL);
//            //ctClass.addField(ctField, String.valueOf(i));//这样无效，agent不会自动拆箱装箱
//            ctClass.addField(ctField, String.valueOf("new Integer("+i+")"));
        }
        byte[] bytes = ctClass.toBytecode();
        TjsStudyNotesApplication.writeClassToDisk("tjs.study.notes.dotest.jvm.class_6_1_类文件结构.TestOutOfMemory",bytes);

        TestClassLoader testClassLoader = new TestClassLoader(bytes);
        Class<?> testClass = testClassLoader.loadClass("tjs.study.notes.dotest.jvm.class_6_1_类文件结构.TestOutOfMemory");
        Object object = testClass.newInstance();
        Field teseField = testClass.getDeclaredField("a"+maxSize);
        System.out.println(teseField.get(object));
    }

    static class TestClassLoader extends ClassLoader {
        private byte[] testClassBttes;

        public TestClassLoader(byte[] testClassBttes) {
            this.testClassBttes = testClassBttes;
        }

        @Override
        protected Class<?> findClass(String className) throws ClassNotFoundException {
            Class clazz = defineClass(className, testClassBttes, 0, testClassBttes.length);
            return clazz;
        }
    }

}
